package com.java.queue;

import java.util.Scanner;

import static java.lang.System.exit;

/**
 * 循环队列
 * @author 19252
 */
public class CycleArrayQueue {
    /**
     * 队列的大小
     */
    private int maxSize;

    /**
     * 指向队列的头部指针
     */
    private int head = 0;

    /**
     * 指向队列的尾部指针
     */
    private int tail = -1;

    /**
     * 循环队列状态标记
     * 使用它来判断 head 与 tail那个指针在前
     * 0 是 tail在前
     * 1 是 head在前
     */
    private int flag = 0;

    /**
     * 数组队列
     */
    private int[] queue;

    public int getMaxSize() {
        return maxSize;
    }

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public int getHead() {
        return head;
    }

    public void setHead(int head) {
        this.head = head;
    }

    public int getTail() {
        return tail;
    }

    public void setTail(int tail) {
        this.tail = tail;
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    public int[] getQueue() {
        return queue;
    }

    public void setQueue(int[] queue) {
        this.queue = queue;
    }

    public static void main(String[] args) {
        // 定义一个输入流，获取输入的数字
        System.out.println("请输入队列的大小（数字）");
        Scanner scanner = new Scanner(System.in);
        CycleArrayQueue queue = new CycleArrayQueue();
        queue.setMaxSize(scanner.nextInt());
        queue.creatQueue(queue.getMaxSize());
        boolean loop = true;
        while (loop) {
            System.out.println("s: 展示队列");
            System.out.println("g: 获取头部");
            System.out.println("a: 添加数据");
            System.out.println("e: 退出操作");
            String c = scanner.next();
            switch (c) {
                case "s":
                    queue.showQueue();
                    break;
                case "g":
                    queue.getData();
                    break;
                case "a":
                    System.out.println("请输入一个数字！");
                    queue.addData(scanner.nextInt());
                    break;
                case "e":
                    loop = false;
                    break;
                default:
                    exit(0);
                    loop = false;
                    break;
            }
        }
    }

    /**
     * 创建一个队列
     * @param maxSize 队列的最大长度
     */
    public void creatQueue(int maxSize) {
        setQueue(new int[maxSize]);
    }

    /**
     * 队列为空，队列中没有数据
     * @return 队列是否为空
     */
    public boolean isEmpty() {
        if (getFlag() == 0){
            if ((getHead() - getTail() == 1) || (getHead() == getMaxSize())) {
                System.out.println("队列为空！");
                return true;
            }
        }
        return false;
    }

    /**
     * 判断队列为满
     * 根据指针的前后关系再来判断
     * @return 队列是否未满
     */
    public boolean isFull(){
        if (getFlag() == 0){
            // tail 在前
            return getTail() == ((maxSize - 1) + getHead());
        }else {
            // head 在前
            if ((getHead() - getTail()) == 1){
                System.out.println("队列为满！");
                return true;
            }
        }
        return false;
    }

    /**
     * 展示数据
     */
    public void showQueue(){
        if (!isEmpty()){
            if (getFlag() == 0){
                // tail 在前
                int start = 0;
                if (getHead() != -1){
                    // 不是第一次循环
                    start = getHead();
                }
                for (int i = start; i < getTail() + 1; i++) {
                    System.out.println("queue[" + i + "] " + getQueue()[i]);
                }
            }else {
                // head 指针在前分两段展示
                for (int i = 0; i < getTail() + 1; i++) {
                    System.out.println("queue[" + i + "] " + getQueue()[i]);
                }
                for (int i = getHead(); i < getQueue().length; i++) {
                    System.out.println("queue[" + i + "] " + getQueue()[i]);
                }
            }
        }
    }

    /**
     * 入队
     * @param data 传入的数据
     */
    public void addData(int data){
        // 如果队列不为满则可以继续添加数据
        if (!isFull()){
            // 判断是否需要改变状态
            // 在这里判断tail指针的位置，判断tail是否需要重新设值
            if (getTail() == getMaxSize() - 1){
                setFlag(1);
                // 将tail设值回到起点，此时head在前
                setTail(-1);
            }
            int[] queue = getQueue();
            // 添加数据，tail加一
            int tail = getTail();
            tail ++;
            queue[tail] = data;
            setTail(tail);
            // 队列的重新设值
            setQueue(queue);
        }
    }

    /**
     * 出队
     */
    public void getData(){
        // 判断队列是否为空，不为空则可以取数据
        if (!isEmpty()){
            if (getHead() == getMaxSize()){
                setFlag(0);
                // 将head设值回到起点，此时tail在前
                setHead(0);
            }
            int head = getHead();
            System.out.println("head = " + head);
            System.out.println("queue[" + head + "] " + getQueue()[head]);
            System.out.println("head" + ++head);
            setHead(head);
        }
    }

}
